package org.light.jpa.verb;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.light.core.Verb;
import org.light.core.Writeable;
import org.light.domain.Domain;
import org.light.domain.Dropdown;
import org.light.domain.Field;
import org.light.domain.JavascriptBlock;
import org.light.domain.JavascriptMethod;
import org.light.domain.Method;
import org.light.domain.Signature;
import org.light.domain.Statement;
import org.light.domain.StatementList;
import org.light.domain.Type;
import org.light.domain.Var;
import org.light.easyui.EasyUIPositions;
import org.light.exception.ValidateException;
import org.light.generator.NamedStatementGenerator;
import org.light.limitedverb.CountSearchByFieldsRecords;
import org.light.utils.DomainTokenUtil;
import org.light.utils.StringUtil;
import org.light.utils.TableStringUtil;
import org.light.utils.WriteableUtil;

public class SearchByFieldsByPage extends org.light.verb.SearchByFieldsByPage {
	@Override
	public Method generateDaoImplMethod() throws Exception {
		return null;
	}

	@Override
	public Method generateDaoMethodDefinition() throws Exception {
		return null;
	}

	@Override
	public Method generateServiceMethodDefinition() throws Exception {
		if (this.denied)
			return null;
		else {
			Method method = new Method();
			method.setStandardName("search" + StringUtil.capFirst(this.domain.getPlural()) + "ByFieldsByPage");
			method.setReturnType(new Type("List", this.domain, this.domain.getPackageToken()));
			method.addAdditionalImport("java.util.List");
			method.addAdditionalImport(this.domain.getPackageToken() + "." + this.domain.getDomainSuffix() + "."
					+ this.domain.getCapFirstDomainNameWithSuffix());
			method.addSignature(new Signature(1, this.domain.getLowerFirstDomainName(), this.domain.getType()));
			method.addSignature(new Signature(2, "pagesize", new Type("Integer")));
			method.addSignature(new Signature(3, "pagenum", new Type("Integer")));
			method.setThrowException(true);

			return method;
		}
	}

	@Override
	public Method generateServiceImplMethod() throws Exception {
		if (this.denied)
			return null;
		else {
			Method method = new Method();
			method.setStandardName("search" + StringUtil.capFirst(this.domain.getPlural()) + "ByFieldsByPage");
			method.setReturnType(new Type("List", this.domain, this.domain.getPackageToken()));
			method.addAdditionalImport(this.domain.getPackageToken() + "." + this.domain.getDomainSuffix() + "."
					+ this.domain.getCapFirstDomainNameWithSuffix());
			method.addSignature(new Signature(1, this.domain.getLowerFirstDomainName(), this.domain.getType()));
			method.addSignature(new Signature(2, "pagesize", new Type("Integer")));
			method.addSignature(new Signature(3, "pagenum", new Type("Integer")));
			method.setThrowException(true);

			method.addAdditionalImport(this.domain.getPackageToken() + "." + this.domain.getDomainSuffix() + "."
					+ this.domain.getCapFirstDomainNameWithSuffix());
			method.addAdditionalImport(this.domain.getPackageToken() + "." + this.domain.getDaoSuffix() + "."
					+ this.domain.getStandardName() + "Dao");
			method.addAdditionalImport(this.domain.getPackageToken() + "." + this.domain.getServiceSuffix() + "."
					+ this.domain.getStandardName() + "Service");

			method.addMetaData("Override");
			if (this.domain.containsDateTime()) {
				method.addAdditionalImport(this.domain.getPackageToken() + ".utils.DateUtil");
			}

			List<Writeable> sList = new ArrayList<Writeable>();
			sList.add(new Statement(1000L, 2, "Integer start = (pagenum-1)*pagesize;"));
			sList.add(new Statement(2000L, 2, "Integer limit = pagesize;"));
			sList.add(new Statement(3000L,2,"String jpql = \"from "+this.domain.getCapFirstDomainNameWithSuffix()+" "+this.domain.getLowerFirstChar()+" where 1=1 \";"));
			long serial = 4000L;
			Set<Field> fields = this.domain.getSearchFields();
			for (Field f : fields) {
				if (!this.deniedFields.contains(f)) {
					if (f.getFieldType().equalsIgnoreCase("string")) {
						sList.add(new Statement(serial, 2,
								"if ("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"() != null) {"));
						sList.add(new Statement(serial + 100, 3,
								"jpql += \" and "+this.domain.getLowerFirstChar()+"."+f.getLowerFirstFieldName()+" like CONCAT('%', '\"+"+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"()+\"','%')\";"));
						sList.add(new Statement(serial + 200, 2,"}"));
					} else if ("date".equalsIgnoreCase(f.getFieldType())){
						sList.add(new Statement(serial, 2,
								"if ("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"() != null) {"));
						sList.add(new Statement(serial + 100, 3,
								"jpql += \" and date("+this.domain.getLowerFirstChar()+"."+f.getLowerFirstFieldName()+") = date('\"+DateUtil.utilDateToString("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"())+\"')\";"));
						sList.add(new Statement(serial + 200, 2,"}"));
					}  else if ("datetime".equalsIgnoreCase(f.getFieldType())){
						sList.add(new Statement(serial, 2,
								"if ("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"() != null) {"));
						sList.add(new Statement(serial + 100, 3,
								"jpql += \" and date("+this.domain.getLowerFirstChar()+"."+f.getLowerFirstFieldName()+") = date('\"+DateUtil.utilDateTimeToString("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"())+\"')\";"));
						sList.add(new Statement(serial + 200, 2,"}"));
					} else if ("float".equalsIgnoreCase(f.getFieldType())||"double".equalsIgnoreCase(f.getFieldType())){
						sList.add(new Statement(serial, 2,
								"if ("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"() != null) {"));
						sList.add(new Statement(serial + 100, 3,
								"jpql += \" and abs("+this.domain.getLowerFirstChar()+"."+f.getLowerFirstFieldName()+" - \"+"+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"()+\") < 0.0001\";"));
						sList.add(new Statement(serial + 200, 2,"}"));
					} else {
						sList.add(new Statement(serial, 2,
								"if ("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"() != null) {"));
						sList.add(new Statement(serial + 100, 3,
								"jpql += \" and "+this.domain.getLowerFirstChar()+"."+f.getLowerFirstFieldName()+" = \"+"+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"();"));
						sList.add(new Statement(serial + 200, 2,"}"));
					}
					serial += 1000L;
				}
			}
			sList.add(new Statement(serial,2,"Query query = entityManager.createQuery(jpql);"));
			sList.add(new Statement(serial+1000L,2,"query.setFirstResult(start); // 设置起始位置"));
			sList.add(new Statement(serial+2000L,2,"query.setMaxResults(limit); // 设置返回结果数量"));
			sList.add(new Statement(serial+3000L,2,"List<"+this.domain.getCapFirstDomainNameWithSuffix()+"> results = query.getResultList();"));
			sList.add(new Statement(serial+4000L,2,"return results;"));
			method.setMethodStatementList(WriteableUtil.merge(sList));
			return method;
		}
	}

	public SearchByFieldsByPage(Domain domain) throws ValidateException{
		super(domain);
	}
}
